package gb.struct;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;



public class Polynomial implements Cloneable {
    private ArrayList<Monomial> internal;
    private Comparator<Monomial> comp;
    
    public Polynomial(Comparator<Monomial> comp) {
    	internal = new ArrayList<Monomial>();
        this.comp = comp;
    }
    
    /**
     * not yet a good implementation
     * @param toAdd
     */
    public void addMono(Monomial toAdd) {
        boolean added = false;
        for (int i = 0; i < internal.size() && !added; i++) {
            if (internal.get(i).match(toAdd)) {
                double toSet = internal.get(i).getCoefficient() + toAdd.getCoefficient();
                if (toSet == 0) {
                    internal.remove(i);
                } else {
                internal.get(i).setCoefficient(toSet);
                }
                added = true;
            }
        }
        if (!added) {
            internal.add(toAdd);
        }
    }
    
    public void setMono(Monomial toAdd, int i) {
        internal.set(i, toAdd);
    }
    
    public Monomial getMono(int pos) {
        return internal.get(pos);
    }
    
    public String toString() {
        StringBuffer buff = new StringBuffer();
        for (int i = 0; i< internal.size(); i++) {
            buff.append(internal.get(i)).append(" ");
        }
        return buff.toString();
    }
    
    public void setComp(Comparator<Monomial> c) {
        comp = c;
    }
    
    public Comparator<Monomial> getComp() {
        return comp;
    }
 
    public void sort() {
        Collections.sort(internal, comp);
    }

    /**
     * probably needs improvement
     * @param toReduce polynomial to determine if it can divide to this polynomial 
     * @return
     */
    public int isDivisible(Polynomial toReduce) {
        int divisible = -1;
        if (internal.size() > 0 && toReduce.size() > 0) {
            //we assume polys are ordered so the leading term is the first one
            Monomial t1 = internal.get(0);
            Monomial t2 = toReduce.getMono(0);
            divisible = 1;
            //if all powers are the same it would they are divisible, but it would lead to infinite reductions so we'll return false for divisible
//            boolean equivalent = true; 
            for (int i = 0; i < Monomial.SIZE && divisible == 1; i++) {
                if (t1.getPower(i) > t2.getPower(i)) {
                    divisible = -1;
//                    equivalent = false;
                }
//                else if (t1.getPower(i) < t2.getPower(i))
//                {
//                	equivalent = false;
//                }
            }
//            if (equivalent) {
//            	divisible = 0;
//            }
        }
        return divisible;
    }
    
    public int size() {
        return internal.size();
    }
    
    public Object clone() {
        Polynomial c = new Polynomial(comp);
        
        for (int i = 0; i < internal.size(); i++) {
            c.addMono((Monomial) internal.get(i).clone());
        }
        
        return c;
    }
    
    public boolean equals(Object ob) {
        if (ob instanceof Polynomial && ob != null) {
            Polynomial p = (Polynomial) ob;
            
            if (internal.size() != p.size()) {
                return false;
            }
            
            for (int i = 0; i<internal.size(); i++) {
                if (! internal.get(i).equals(p.getMono(i))) {
                    return false;
                }
            }
            return true;
        } else {
            return super.equals(ob);
        }
    }
}
